//
//  YSRequestManager.m
//  Pods
//
//  Created by zhanglu on 16/3/3.
//
//

#import "YSRequestManager.h"
#import "YSRequestConfig.h"

#import <AFNetworking/AFNetworking.h>


@interface YSRequestManager ()
{
    NSMutableDictionary *_requestsRecord;
}

@end

@implementation YSRequestManager

+ (instancetype)manager
{
    static YSRequestManager *manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[YSRequestManager alloc] init];
    });
    return manager;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        _manager = [AFHTTPSessionManager manager];
        // 在request的时候会重新生成responseSerializer，这里改了没用啊。。
        // _manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/plain",@"application/json", @"text/html",@"text/json",@"text/javascript", nil];//设置相应内容类型
        _manager.operationQueue.maxConcurrentOperationCount = self.maxConcurrentOperationCount;
        // 如果reachable没有连上有可能是没有开始monitoring，这里手动开启一下，保证ReachabilityManager正常工作。
        if ([AFNetworkReachabilityManager sharedManager].networkReachabilityStatus == AFNetworkReachabilityStatusUnknown) {
            [[AFNetworkReachabilityManager sharedManager] startMonitoring];
        }
    }
    return self;
}

- (NSInteger)maxConcurrentOperationCount
{
    return _maxConcurrentOperationCount > 0? _maxConcurrentOperationCount : 4;
}

- (void) sendWithRequest:(YSRequest *)request
                 success: (void(^ _Nonnull)(id _Nonnull response)) success
                 failure: (void(^ _Nonnull)(YSRequest * _Nonnull request)) failure
{
    // 判断如果没有连接到网络就不发这个请求
    if ([AFNetworkReachabilityManager sharedManager].networkReachabilityStatus == AFNetworkReachabilityStatusNotReachable) {
        request.error = [NSError errorWithDomain:@"SEND_NOTE" code:0 userInfo:@{@"message": @"似乎断开了与互联网的连接"}];
        failure(request);
        return;
    }
    
    // Https 验证
    _manager.securityPolicy.allowInvalidCertificates = YES;  //允许非权威机构颁发的证书
    
    _manager.securityPolicy.validatesDomainName = NO;  //也不验证域名一致性
    
    id param = request.requestParam;
    
    if (request.requestSerializerType == YSRequestSerializerTypeHTTP) {
        _manager.requestSerializer = [AFHTTPRequestSerializer serializer];
    } else if (request.requestSerializerType == YSRequestSerializerTypeJSON) {
        _manager.requestSerializer = [AFJSONRequestSerializer serializer];
    }
    
    if (request.responseSerializerType == YSResponseSerializerTypeHTTP) {
        _manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    } else if (request.responseSerializerType == YSResponseSerializerTypeJSON) {
        _manager.responseSerializer = [AFJSONResponseSerializer serializer];
        ((AFJSONResponseSerializer *)_manager.responseSerializer).removesKeysWithNullValues = YES;
    }
    _manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/plain",@"application/json", @"text/html",@"text/json",@"text/javascript", nil];//设置相应内容类型
    
    _manager.requestSerializer.timeoutInterval = request.timeoutInterval;
    void(^successCallback)(NSURLSessionDataTask * , id) = ^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {
        request.response = (NSHTTPURLResponse *)task.response;
        success(responseObject);
    };
    
    void(^failureCallback)(NSURLSessionDataTask * , NSError *) = ^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        request.response = (NSHTTPURLResponse *)task.response;// 失败的字段
        NSMutableDictionary *dict = [error.userInfo mutableCopy];
        if (dict[@"message"] == nil) {
            [dict addEntriesFromDictionary:@{@"message" : @"请求失败"}];
        }
        request.error = [NSError errorWithDomain:@"Net_error" code:0 userInfo:dict];
        failure(request);
    };
    
    switch (request.requestMethod) {
        case YSRequestMethodGet:{
            request.sessionDataTask = [_manager GET:request.requestUrl parameters:param success:successCallback failure:failureCallback];
        }
            break;
        case YSRequestMethodPost:{
            if (request.imageData) {
                request.sessionDataTask =
                [_manager POST:request.requestUrl parameters:param constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
                    [formData appendPartWithFileData:request.imageData name:request.imageName fileName:[NSString stringWithFormat:@"%@.%@", request.imageName,[request.imageType componentsSeparatedByString:@"/"].lastObject] mimeType:request.imageType];
                } success:successCallback failure:failureCallback];
            } else {
                request.sessionDataTask = [_manager POST:request.requestUrl parameters:param success:successCallback failure:failureCallback];
            }
        }
            break;
        case YSRequestMethodPut:{
            request.sessionDataTask = [_manager PUT:request.requestUrl parameters:param success:successCallback failure:failureCallback];
        }
            break;
        case YSRequestMethodDelete:{
            request.sessionDataTask = [_manager DELETE:request.requestUrl parameters:param success:successCallback failure:failureCallback];
        }
            break;
        case YSRequestMethodPatch:{
            request.sessionDataTask = [_manager PATCH:request.requestUrl parameters:param success:successCallback failure:failureCallback];
        }
            break;
        default:
            //            YSAFLog(@"Error, unsupport method type");
            break;
    }
}

- (NSString *)requestHashKey:(NSURLSessionDataTask *)sessionDataTask
{
    NSString *key = [NSString stringWithFormat:@"%lu", (unsigned long)[sessionDataTask hash]];
    return key;
}

- (void)addOperation:(YSRequest *)request
{
    if (request.sessionDataTask != nil) {
        NSString *key = [self requestHashKey:request.sessionDataTask];
        _requestsRecord[key] = request;
    }
}

- (void)removeOperation:(NSURLSessionDataTask *)sessionDataTask
{
    NSString *key = [self requestHashKey:sessionDataTask];
    [_requestsRecord removeObjectForKey:key];
}

- (void)cancelRequest:(YSRequest *)request
{
    [request.sessionDataTask cancel];
    [self removeOperation:request.sessionDataTask];
}

- (void)cancelAllRequests
{
    NSDictionary *copyRecord = [_requestsRecord copy];
    for (NSString *key in copyRecord) {
        YSRequest *request = copyRecord[key];
        [self cancelRequest:request];
    }
}

@end
